package conf

import (
	"flag"
	"fmt"
	"os"
	"time"

	"github.com/nsqio/go-nsq"
	"github.com/spf13/viper"
)

// Tag
var (
	Conf       = &Config{}
	configFile string
)

// Config 配置
type Config struct {
	Env      *Env        `mapstructure:"env"`
	ORM      *ORM        `mapstructure:"orm"`
	Redis    *Redis      `mapstructure:"redis"`
	HTTP     *HTTP       `mapstructure:"http"`
	NSQ      *nsq.Config `mapstructure:"nsq"`
	NSQAddr  *NSQAddr    `mapstructure:"nsq_conf"`
	Keys     *Keys       `mapstructure:"keys"`
	Cos      *Cos        `mapstructure:"cos"`
	Oss      *Oss        `mapstructure:"oss"`
	Callback *Callback   `mapstructure:"callback"`
	Alipay   *Alipay     `mapstructure:"alipay"`
	Biz      *Biz        `mapstructure:"biz"`
}

// NSQ 定时任务配置
type NSQAddr struct {
	NSQAddress    string `mapstructure:"nsq_address"`
	LookupAddress string `mapstructure:"lookup_address"`
}

// HTTP 服务端口配置
type HTTP struct {
	Port      string `mapstructure:"port"`
	RpcPort   string `mapstructure:"rpc_port"`
	PProfPort string `mapstructure:"pprof_port"`
}

type Env struct {
	Name                  string `mapstructure:"name"`
	ObjectStorageProvider string `mapstructure:"object_storage_provider"`
}

type ORM struct {
	DSN         string        `mapstructure:"dsn"`
	Active      int           `mapstructure:"active"`
	Idle        int           `mapstructure:"idle"`
	IdleTimeout time.Duration `mapstructure:"idle_timeout"`
}

type Redis struct {
	Addr     string `mapstructure:"addr"`
	Password string `mapstructure:"password"`
	DB       int    `mapstructure:"db"`
}

type Keys struct {
	JWTPublicKey  string `mapstructure:"jwt_pub_key"`
	JWTPrivateKey string `mapstructure:"jwt_pri_key"`
}

type Cos struct {
	WxpayBucketUrl string `mapstructure:"wxpay_bucket_url"`
	BgpBucketUrl string `mapstructure:"bgp_bucket_url"`
	SecretID  string `mapstructure:"secret_id"`
	SecretKey string `mapstructure:"secret_key"`
}

type Oss struct {
	Endpoint        string `mapstructure:"endpoint"`
	AccessKeyID     string `mapstructure:"access_key_id"`
	AccessKeySecret string `mapstructure:"access_key_secret"`
	BucketName      string `mapstructure:"bucket_name"`
}
type Callback struct {
	Endpoint string `mapstructure:"endpoint"`
}

type Alipay struct {
	AppID         string `mapstructure:"app_id"`
	PlatPublicKey string `mapstructure:"plat_public_key"`
	AppPrivateKey string `mapstructure:"app_private_key"`
}

type Biz struct {
	MchIDAsService string `mapstructure:"mch_id_as_service"`
	MchIDAsProfit  string `mapstructure:"mch_id_as_profit"`
}

// NewConfig new config
func NewConfig() *Config {
	NSQ := nsq.NewConfig()
	NSQ.MaxInFlight = 5
	NSQ.MsgTimeout = 3 * time.Second
	// 默认设置
	return &Config{
		Env: &Env{
			Name: "dev",
		},
		ORM: &ORM{
			DSN:         "",
			Active:      5,
			Idle:        5,
			IdleTimeout: time.Hour * 4,
		},
		Redis: &Redis{
			Addr:     "127.0.0.1:6379",
			Password: "redis123#",
			DB:       3,
		},
		HTTP: &HTTP{
			Port:      ":8999",
			RpcPort:   ":7777",
			PProfPort: ":9999",
		},
		NSQ: NSQ,
		NSQAddr: &NSQAddr{
			NSQAddress:    "10.0.244.37:4150",
			LookupAddress: "10.0.244.37:4161",
		},
		Keys: &Keys{
			JWTPublicKey:  "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8vOtJEQmp14qhEeNzV6Dta0ou\nkt+vktu8WU2J1K6MPqYaGwj3ML8Nb4x436j+TLunQgyj5JqJfKJQo7oXi7Yhaq+n\nQ1J39pOKLYm6Le01NWV6fIdccNdOJ0VIoNyBbCBYdkodod/vAYHuStmupehBhoES\nYtowgrQ1hd5B6Rh1MwIDAQAB\n-----END PUBLIC KEY-----",
			JWTPrivateKey: "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQC8vOtJEQmp14qhEeNzV6Dta0oukt+vktu8WU2J1K6MPqYaGwj3\nML8Nb4x436j+TLunQgyj5JqJfKJQo7oXi7Yhaq+nQ1J39pOKLYm6Le01NWV6fIdc\ncNdOJ0VIoNyBbCBYdkodod/vAYHuStmupehBhoESYtowgrQ1hd5B6Rh1MwIDAQAB\nAoGBALJ7laWLTzAmfRrE5+tzuuPKymQw0QggQVxkt0bYshg+RqX5WwkoOARksNq9\n5/pUZkFN3NZAoUPTcUwBCUKrBJgErfQgqmdVL6lUgWIA+2lrPczVyDvYqYhKixip\nu2NbNOiVQDPz92Ocgr0HYUxif10hjW+U/mImruE83gIVh3JBAkEA61jkyo3kvTy8\nMh0hPIDnQQOZkZ5s3IV0nAb9diti2QAvaUVVTHsUatx9ocqy17s7YHG9e01w/4ET\nUuvHuLVoNwJBAM1M8SMWj1OMRxM0l5yKf226G8oCVzztKFbrRW4WSEiKtwlY8X2Q\nHJA1k4OgGheNrqy1No8hMKNIP+yQeFLppOUCQGlBAmHMf+ZaSVioSnsCs2oSMBY+\nIjWlwfcd8TFuSfD+8jVEetePnBwGrHE1dDKjW/TQKYwBoG3Ezl2hcVscVpUCQHf3\nNhFi5W3U0tOOL+nxpHTiA8sPgxq/Gotv/6pMqwB4zmxP5Q2SYJ6EMCcCLz0ENcYG\nPlN0+Y7wcSozYZxRm2ECQDY/ujOuI0iCB14PCSTywujCAzCIobRgdkiAs9szUxo0\nmPVooyZpW8VIpjTW5fQOujbAyk6lgdASvRpD/dgCL/4=\n-----END RSA PRIVATE KEY-----",
		},
		Cos: &Cos{},
		Oss: &Oss{
			Endpoint:        "https://oss-cn-hangzhou.aliyuncs.com",
			AccessKeyID:     "LTAI4GGmXYkUdNjssU2Sp5nJ",
			AccessKeySecret: "kZb6zr7shZyonZx8U2moOmKCBM8Nuv",
			BucketName:      "customer-uploaded-files",
		},
		Callback: &Callback{
			Endpoint: "https://wxpay.dev.luedongtech.com",
		},
		Alipay: &Alipay{
			AppID:         "2016020101133396",
			PlatPublicKey: "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkr\nIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsra\nprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUr\nCmZYI/FCEa3/cNMW0QIDAQAB\n-----END PUBLIC KEY-----",
			AppPrivateKey: "-----BEGIN RSA PRIVATE KEY-----\nMIICWwIBAAKBgQC4UcQm06Kz9OH8Q6l2wxSOt9BdObuuC1hJQrQNbkqHU7SM1aI4\ng156fbAoaEZdb7k2bQSyf6PNWYNS+cl9LPsggbYZ1ZapbqgEt39N4sMKOPUEwMco\n4P9ZQL6C2+1YfqUc4zZKCqiocgXy0tuV3kKWYleOM/Y+J/2PfAUtKF2p3wIDAQAB\nAoGANAQnRgnNzdla+TUjGvf80jX/oH+NfpWHCc3AQFYSxFQUDPaxPB+exxS3ZP/g\nc7f23ewwOiuZT3dmf0Es4p2SFOQypacVFyzi4Dj/cvJGxze8Ek047jS5wc6tZiQH\njPcmPB0i2/wAJt9ThINdBnSzKrjRhfWy1aRay7fNk1BTmAECQQDvuYRR9yGDifc4\nT8at2xvUbPKavDFNUx2SNq233A2+DESFa9w3ZirVjiKzLR4/d60Gt/n9j5PssP4s\nyECrGIwBAkEAxNVKNLO44+e8otUPc//s+Uhwzp3ASNT2JkVv4kFO+mkaGErkGnyS\nWmWSbvjziK3TFkYOAGFUzH2+6MPETv+13wJAJKIl/VyVq4NG2z0dsG2+V/z6Kfk+\nU4GzECf47hLbqsI3KmhsM68SNqZM2TK435wLPe6Zbk0lntMBVJiZgUv0AQJAO/BL\ngZL9CYHHArro0sUrb5nsqC6HoGYhcvQQJxEGMOESjjU4Ewy+MILfvaVX29Y7Anxg\nxSLehMsB+LWssPXTdwJAJjRaoDllB2eO5wXAuKZNqYzpI6T3tK7tNG51SDlwkv3W\nMzuihwkv/tys/pWcFtwJFimbL34e/4dpWB1sHxtA1Q==\n-----END RSA PRIVATE KEY-----",
		},
		Biz: &Biz{
			MchIDAsService: "",
			MchIDAsProfit: "",
		},
	}
}

func init() {
	flag.StringVar(&configFile, "c", "cmd/config.toml", "path of mall config file.")
}

func overrideConfByEnvVars(config *Config) {
	EnvNsqd, ok := os.LookupEnv("NSQD_ADDRESS")
	if ok && EnvNsqd != "" {
		config.NSQAddr.NSQAddress = EnvNsqd
	}
}

// Init is func to initial log config
func Init() (err error) {
	Conf = NewConfig()
	viper.SetConfigFile(configFile)

	if err = viper.ReadInConfig(); err != nil {
		return err
	}

	if err = viper.Unmarshal(&Conf); err != nil {
		panic(fmt.Errorf("unable to decode into struct：%s ", err))
	}
	overrideConfByEnvVars(Conf)
	return nil
}
